package org.juggers.client;

import org.adamtacy.client.ui.effects.impl.SlideRight;
import org.juggers.domain.JugEvent;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.gdata.client.DateTime;
import com.google.gwt.gdata.client.GData;
import com.google.gwt.gdata.client.GDataSystemPackage;
import com.google.gwt.gdata.client.calendar.CalendarEventEntry;
import com.google.gwt.gdata.client.calendar.CalendarEventFeed;
import com.google.gwt.gdata.client.calendar.CalendarEventFeedCallback;
import com.google.gwt.gdata.client.calendar.CalendarEventQuery;
import com.google.gwt.gdata.client.calendar.CalendarService;
import com.google.gwt.gdata.client.impl.CallErrorException;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Juggers
    implements EntryPoint
{
    
    private CalendarService calendar;
    
    private final static String GCAL_FEED_URI = "http://www.google.com/calendar/feeds/admin@juggers.org/public/full";
    
    /**
     * This is the entry point method.
     */
    public void onModuleLoad()
    {
        Log.setUncaughtExceptionHandler();
        DeferredCommand.addCommand( new Command()
        {
            public void execute()
            {
            	doOnModuleLoad();
            }
        } );
    }
    
    /**
     * Deferred load
     */
    public void doOnModuleLoad()
    {
    	if ( !GData.isLoaded( GDataSystemPackage.CALENDAR ) )
        {
            Log.info( "Loading the GData Calendar package..." );
            GData.loadGDataApi( null, new Runnable()
            {
                public void run()
                {
                    getEvents();
                }
            }, GDataSystemPackage.CALENDAR );
        }
        else
        {
        	getEvents();
        }
    }

    /**
     * Retrieve the Calendar events feed using the Calendar service and the events feed uri. In GData all get, insert,
     * update and delete methods always receive a callback defining success and failure handlers. Here, the failure
     * handler displays an error message while the success handler calls showData to display the event entries.
     */
    private void getEvents()
    {
    	calendar = CalendarService.newInstance( "Juggers.org" );
    	
    	CalendarEventQuery query = CalendarEventQuery.newInstance( GCAL_FEED_URI );
    	query.setFutureEvents( true );
    	query.setOrderBy( CalendarEventQuery.ORDERBY_START_TIME );
    	query.setSortOrder( CalendarEventQuery.SORTORDER_ASCENDING );
    	
    	calendar.getEventsFeed( query, new CalendarEventFeedCallback() {
    		
            public void onFailure( CallErrorException caught )
            {
                Log.error( "Google Calendar Feed error", caught );
                Window.alert( "An error occurred while retrieving the Events feed: " + caught.getMessage() );
            }

            public void onSuccess( CalendarEventFeed result )
            {
            	DOM.getElementById( "loading" ).removeFromParent();
            	
                CalendarEventEntry[] entries = result.getEntries();
                if ( entries.length == 0 )
                {
                    Window.alert( "There are no Calendar events." );
                }
                else
                {
                    showData( entries );
                }
            }
        } );
    }

    /**
     * Displays a set of Calendar event entries in a tabular fashion with the help of a GWT FlexTable widget. The data
     * fields Title, URL and Updated are displayed.
     * 
     * @param entries The Calendar event entries to display.
     */
    private void showData( CalendarEventEntry[] entries )
    {
        RootPanel root = RootPanel.get( "events" );

        for ( CalendarEventEntry entry : entries )
        {
            if ( Log.isDebugEnabled() )
            {
                Log.debug( "Display event " + entry.getTitle().getText() );
            }
            EventWidget widget = new EventWidget( convert( entry ) );
            root.add( widget );
            SlideRight effect = new SlideRight( widget.getElement() );
            effect.setDuration( 1.0 );
            effect.play();
        }
    }

    private JugEvent convert( CalendarEventEntry entry )
    {
        JugEvent event = new JugEvent( entry.getId().getValue() );
        event.setTitle( entry.getTitle().getText() );
        String text = entry.getContent().getText();

        int idx = text.indexOf( '\n' );
        if ( idx > 0 ) // more than one line
        {
            String[] speakersList = text.substring( 0, idx ).split( "," );
            for ( String speaker : speakersList )
            {
                event.addSpeaker( speaker );
            }
            event.setSummary( text.substring( idx + 1 ) );
        }
        else
        {
            event.setSummary( text );
        }

        String location = entry.getLocations()[0].getValueString();
        event.setLocation( location );

        DateTime dateTime = entry.getTimes()[0].getStartTime();
        event.setDateTime( dateTime.getDate() );
        return event;
    }
}
